#include "base_scene.h"
#include "base_entity.h"
#include "utils.h"
#include <vector>
#include <algorithm>

USING_NS_CC;
using std::vector;
using std::sort;

BaseScene::~BaseScene()
{
    removeAllEntity();
    CC_SAFE_RELEASE(_stage);
}

bool BaseScene::init()
{
    _stage = Layer::create();
    _stage->retain();

    _farLayer = Layer::create();
    _farLayer->setZOrder(0);
    _stage->addChild(_farLayer);

    _bottomEffectLayer = Layer::create();
    _bottomEffectLayer->setZOrder(2);
    _stage->addChild(_bottomEffectLayer);

    _goLayer = Layer::create();
    _goLayer->setZOrder(3);
    _stage->addChild(_goLayer);

    _nearLayer = Layer::create();
    _nearLayer->setZOrder(4);
    _stage->addChild(_nearLayer);

    _topEffectLayer = Layer::create();
    _topEffectLayer->setZOrder(5);
    _stage->addChild(_topEffectLayer);

	return true;
}

void BaseScene::setup(int sceneId_)
{
    _sceneId = sceneId_;

    _map = GameMap::create("map/fb_lian_cheng_zai/fb_lian_cheng_zai.tmx");
    _map->setZOrder(1);
    _stage->addChild(_map);

    _camera = new SceneCamera();
    _camera->setViewSize(Size(960, 640));
    _camera->setViewableRange(Rect(0, 0, _map->getMapWidth()*_map->getCellWidth(), _map->getMapHeight()*_map->getCellHeight()));
    _camera->lookAt(Point(0, 0));
}

void BaseScene::render(long tick)
{
    _camera->run(tick);
    _goLayer->setPosition(-_camera->getPosition().x, -_camera->getPosition().y);
    _map->setOffset(-_camera->getPosition().x, -_camera->getPosition().y);

    if ( _entities.size() <= 0 )
        return;

    for ( BaseEntity *entity : _entities  )
    {
        entity->disappear ? entity->removeFromScene() : entity->run(tick);
    }
    
    vector<BaseEntity*> renderList;
	for ( BaseEntity *entity : _entities )
    {
        if ( entity->inScreen )
        {
            renderList.push_back(entity);
            entity->render(tick);
        }
    }
    sort(renderList.begin(), renderList.end(), depthCompare);
    for ( int i = renderList.size() - 1; i >= 0; --i )
    {
        renderList[i]->setZOrder(i);
    }
}

void BaseScene::addEntity(BaseEntity *entity)
{
    if ( _entities.find(entity) == _entities.end() )
    {
        _entities.pushBack(entity);
        _goLayer->addChild(entity);
    }
}

void BaseScene::removeEntity(BaseEntity *entity)
{
    Vector<BaseEntity*>::iterator iter = _entities.find(entity);
    if ( iter != _entities.end() )
    {
        _entities.erase(iter);
        entity->removeFromParent();
    }
}

void BaseScene::removeEntity(int id)
{
    for ( Vector<BaseEntity*>::iterator iter = _entities.begin(); iter != _entities.end(); iter++ )
    {
        if ( (*iter)->id == id )
        {
            _entities.erase(iter);
            (*iter)->removeFromParent();
        }
    }
}

void BaseScene::removeAllEntity()
{
    for ( Vector<BaseEntity*>::iterator iter = _entities.begin(); iter != _entities.end(); iter++ )
    {
        _entities.erase(iter);
        (*iter)->removeFromParent();
    }
}

BaseEntity* BaseScene::getEntity(int id)
{
    for ( BaseEntity *entity : _entities )
    {
        if ( entity->id == id )
            return entity;
    }
    return nullptr;
}

bool depthCompare(BaseEntity *entity1, BaseEntity *entity2)
{
    return entity1->getPosition().y < entity2->getPosition().y;
}